package com.yxsk.relay.job.admin.data.service;

import com.yxsk.relay.job.admin.data.entity.BaseEntity;
import com.yxsk.relay.job.admin.data.repository.BaseRepository;
import com.yxsk.relay.job.admin.exception.data.DataPersistenceException;
import com.yxsk.relay.job.admin.utils.IdUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.text.MessageFormat;
import java.util.List;
import java.util.Optional;

/**
 * @Author 11376
 * @CreaTime 2019/6/22 11:08
 * @Description
 */
public abstract class AbstractService<T extends BaseEntity, R extends BaseRepository> {

    @Autowired
    protected R repository;

    @Transactional
    public void addEntity(T entity) {
        Assert.notNull(entity, "Add entity not be null");
        if (!StringUtils.hasLength(entity.getId())) {
            entity.setId(IdUtils.nextId());
        }
        this.repository.save(entity);
    }

    @Transactional
    public void addEntities(List<T> entities) {
        Assert.notEmpty(entities, "Entities not be empty");
        entities.stream().forEach(t -> this.repository.save(t));
    }

    @Transactional
    public void deleteById(String id) {
        Assert.hasLength(id, "Id not be null");
        Optional optional = this.repository.findById(id);
        if (!optional.isPresent()) {
            throw new DataPersistenceException(MessageFormat.format("Not found entity by id, id[{1}]", id));
        }
        Object o = optional.get();
        T t = (T) o;
        t.setDelFlag(BaseEntity.DelFlagEnum.DELETED.getFlag());
        this.repository.save(t);
    }

    @Transactional
    public void updateById(T entity) {
        Assert.hasLength(entity.getId(), "Id not be null");
        Optional optional = this.repository.findById(entity.getId());
        if (!optional.isPresent()) {
            throw new DataPersistenceException(MessageFormat.format("Not found old entity by id, entity[{0}], id[{1}]", entity.getClass(), entity.getId()));
        }
        Object o = optional.get();
        this.repository.save(entity);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public T findById(String id) {
        Assert.hasLength(id, "Id not be null");
        Optional optional = this.repository.findById(id);
        if (!optional.isPresent()) {
            return null;
        }
        return (T) optional.get();
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public List<T> findAll() {
        return this.repository.findAll();
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public List<T> findAllNormalEntities() {
        return this.repository.findByDelFlag(BaseEntity.DelFlagEnum.NORMAL.getFlag());
    }


    @Transactional(propagation = Propagation.SUPPORTS)
    public T findPage(Pageable pageable) {
        return (T) this.repository.findAll(pageable);
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public Long count(T t) {
        Example example = Example.of(t);
        return this.repository.count(example);
    }

}
